package com.tianyuan.lims.dms.controller.app;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Inject;
import com.jfinal.core.Controller;
import com.jfinal.core.paragetter.Para;
import com.jfinal.json.FastJson;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import com.tianyuan.lims.common.config.redis.Redis;
import com.tianyuan.lims.common.config.redis.RedisManager;
import com.tianyuan.lims.common.constant.BaseConstant;
import com.tianyuan.lims.erp.admin.entity.AdminUser;
import com.tianyuan.lims.erp.admin.service.AdminRoleService;
import com.tianyuan.lims.erp.admin.service.AdminUserService;
import com.tianyuan.lims.utils.BaseUtil;
import com.tianyuan.lims.utils.CommonCryptogramUtil;
import com.tianyuan.lims.utils.R;
import com.tianyuan.lims.utils.ValidateCodeUtils;
import io.github.yedaxia.apidocs.ApiDoc;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

/**
 * 用户登录
 *
 * @author z
 */
public class ApiLoginController extends Controller {
    @Inject
    private AdminUserService adminUserService;

    @Inject
    private AdminRoleService adminRoleService;

//    @Inject
//    private HwSmsSenderService hwSmsSenderService;

    public final static Prop prop = PropKit.use("config/tylims-config.cfg");

//    public void index() {
//         //redirect("/index.html");
//        //renderJson("ok");
//        //redirect("/app/index");
//    }

    public void apidoc() {
        redirect("/japidoc/V1.0/index.html");
    }

    /**
     * @param username 用户名
     * @param password 密码
     * @author zhangzhiwei
     * 用户登录
     */

    public void loginV1(
            @Para("username") String username,
            @Para("password") String password,
            @Para("captcha") String captcha,  // 前端传递的验证码
            @Para("cid") String cid,          // 验证码标识（通常对应session key）
            @Para("d") String d               // 预留参数，根据实际用途处理
    ) {
        // 1. 验证码校验

        String rawData = getRawData(); // 获取请求体中的原始 JSON 字符串
        if (StrUtil.isEmpty(rawData)) {
            renderJson(R.error("请求参数不能为空（请使用JSON格式提交）"));
            return;
        }

        // 解析 JSON 为 JSONObject（使用 fastjson 解析，与原有逻辑保持一致）
        JSONObject json;
        try {
            json = JSONObject.parseObject(rawData);
        } catch (Exception e) {
            renderJson(R.error("JSON格式错误，请检查请求参数"));
            return;
        }

        // 2. 从 JSON 中提取参数
         username = json.getString("username");
         password = json.getString("password");
         captcha = json.getString("captcha");
         cid = json.getString("cid");
         d = json.getString("d"); // 预留参数

//        if (StrUtil.isEmpty(captcha)) {
//            renderJson(R.error("请输入验证码！"));
//            return;
//        }
//        if (StrUtil.isEmpty(cid)) {
//            renderJson(R.error("验证码标识不能为空！"));
//            return;
//        }
//
//        // 从Session获取存储的验证码（注意：key需与生成验证码时存入的一致）
//        // 参考之前验证码逻辑，数学验证码用"kaptchaCodeMath"，普通用"kaptchaCode"，这里统一用cid作为key更灵活
//        String sessionCaptcha = (String) getSession().getAttribute(cid);
//        if (StrUtil.isEmpty(sessionCaptcha)) {
//            renderJson(R.error("验证码已过期，请刷新重试！"));
//            return;
//        }
//
//        // 忽略大小写校验验证码（根据实际需求决定是否开启）
//        if (!sessionCaptcha.equalsIgnoreCase(captcha)) {
//            renderJson(R.error("验证码错误！"));
//            return;
//        }

        // 2. 密码错误次数限制（原逻辑保留）
        String key = BaseConstant.USER_LOGIN_ERROR_KEY + username;
        Redis redis = RedisManager.getRedis();
        boolean enableRedis = redis == null ? false : true;
        if (enableRedis) {
            long beforeTime = System.currentTimeMillis() - 60 * 5 * 1000; // 5分钟内
            if (redis.exists(key)) {
                // 5分钟内错误次数 >=15 次则限制登录
                if (redis.zcount(key, beforeTime, System.currentTimeMillis()) >= 15) {
                    Set<?> zrevrange = redis.zrevrange(key, 4, 5);
                    Long time = (Long) zrevrange.iterator().next() + 60 * 5 * 1000;
                    long expire = (time - System.currentTimeMillis()) / 1000;
                    renderJson(R.error("密码错误次数过多，请等" + expire + "秒后再重试！"));
                    return;
                }
            }
            // 记录本次登录尝试（无论成败，用于统计错误次数）
            redis.zadd(key, System.currentTimeMillis(), System.currentTimeMillis());
        }

        // 3. 用户名密码非空校验（原逻辑优化）
        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
            // 尝试从rawData中解析（兼容JSON格式提交）
            try {
                Map<String, Object> args = FastJson.getJson().parse(getRawData(), Map.class);
                if (args.containsKey("username")) username = args.get("username").toString();
                if (args.containsKey("password")) password = args.get("password").toString();
            } catch (Exception e) {
                // 解析失败不处理，继续校验
            }
            if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
                renderJson(R.error("请输入用户名和密码！"));
                return;
            }
        }

        // 4. 用户信息校验（原逻辑保留）
        AdminUser user = AdminUser.dao.findFirst(Db.getSql("admin.user.queryByUserName"), username.trim());
        if (user == null) {
            renderJson(R.error("用户名或密码错误！"));
            return;
        }
        if (user.getStatus() == 0) {
            renderJson(R.error("账户被禁用！"));
            return;
        }

        // 5. 密码校验及登录成功处理（原逻辑保留）
        if (BaseUtil.verify(username + password, user.getSalt(), user.getPassword())) {
            // 更新用户状态为正常（如果之前是锁定状态）
            if (user.getStatus() == 2) {
                user.setStatus(1);
            }

            // 生成token
            String token = IdUtil.simpleUUID();
            // 更新登录信息
            user.setLastLoginIp(ServletUtil.getClientIP(getRequest()));
            user.setLastLoginTime(new Date());
            user.update();
            // 查询用户角色
            user.setRoles(adminRoleService.queryRoleIdsByUserId(user.getUserId()));
            Integer type = getParaToInt("type", 1);

            // 存储token到Redis
            if (enableRedis) {
                redis.del(key); // 登录成功，清除错误次数记录
                redis.setex(token, 3600, user); // token有效期1小时
                BaseUtil.setToken(user.getUserId(), token, type);
            }

            // 移除敏感字段
            user.remove("password", "salt");
            // 存入session
            setSessionAttr("user", user);
            setSessionAttr("token", token);

            // 返回登录成功信息
            renderJson(R.ok()
                    .put("Admin-Token", token)
                    .put("user", user)
                    .put("auth", adminRoleService.auth(user.getUserId())));
        } else {
            Log.getLog(getClass()).warn("用户[" + username + "]登录失败：密码错误");
            renderJson(R.error("用户名或密码错误！"));
        }
    }

//    public void loginV1(@Para("username") String username, @Para("password") String password) {
//
//        String key = BaseConstant.USER_LOGIN_ERROR_KEY + username;
//        Redis redis = RedisManager.getRedis();
//        boolean enableRedis = redis == null ? false : true;
//        if (enableRedis) {
//            long beforeTime = System.currentTimeMillis() - 60 * 5 * 1000;
//            if (redis.exists(key)) {
//                if (redis.zcount(key, beforeTime, System.currentTimeMillis()) >= 15) {
//                    Set zrevrange = redis.zrevrange(key, 4, 5);
//                    Long time = (Long) zrevrange.iterator().next() + 60 * 5 * 1000;
//                    long expire = (time - System.currentTimeMillis()) / 1000;
//                    renderJson(R.error("密码错误次数过多，请等" + expire + "秒后在重试！"));
//                    return;
//                }
//            }
//            redis.zadd(key, System.currentTimeMillis(), System.currentTimeMillis());
//        }
//        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
//            Map<String, Object> args = FastJson.getJson().parse(getRawData(), Map.class);
//            if (args.get("username") != null) username = args.get("username").toString();
//            if (args.get("username") != null) password = args.get("password").toString();
//            if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
//                renderJson(R.error("请输入用户名和密码！"));
//                return;
//            }
//        }
//        AdminUser user = AdminUser.dao.findFirst(Db.getSql("admin.user.queryByUserName"), username.trim());
//        if (user == null) {
//            renderJson(R.error("用户名或密码错误！"));
//            return;
//        }
//        if (user.getStatus() == 0) {
//            renderJson(R.error("账户被禁用！"));
//            return;
//        }
//        if (BaseUtil.verify(username + password, user.getSalt(), user.getPassword())) {
//            if (user.getStatus() == 2) {
//                user.setStatus(1);
//            }
//
//            String token = IdUtil.simpleUUID();
//            user.setLastLoginIp(ServletUtil.getClientIP(getRequest()));
//            user.setLastLoginTime(new Date());
//            user.update();
//            user.setRoles(adminRoleService.queryRoleIdsByUserId(user.getUserId()));
//            Integer type = getParaToInt("type", 1);
//
//            if (enableRedis) {
//                redis.del(key);
//                redis.setex(token, 3600, user);
//                BaseUtil.setToken(user.getUserId(), token, type);
//            }
//
//            user.remove("password", "salt");
//            setSessionAttr("user", user);
//            setSessionAttr("token", token);
//
//            renderJson(R.ok().put("Admin-Token", token).put("user", user).put("auth", adminRoleService.auth(user.getUserId())));
//        } else {
//            Log.getLog(getClass()).warn("用户登录失败");
//            renderJson(R.error("用户名或密码错误！"));
//        }
//
//    }




    public void resetPassword(@Para("userIds") String ids, @Para("password") String pwd) {
        if (StrUtil.isEmpty(ids) || StrUtil.isEmpty(pwd)) {
            if (StrUtil.isEmpty(getRawData())) {
                renderJson(R.error("参数！"));
                return;
            }

            Map<String, Object> args = FastJson.getJson().parse(getRawData(), Map.class);
            if (args.get("userIds") != null) ids = args.get("userIds").toString();
            if (args.get("pwd") != null) pwd = args.get("password").toString();
            if (StrUtil.isEmpty(ids) || StrUtil.isEmpty(pwd)) {
                renderJson(R.error("请输入用户名和密码！"));
                return;
            }
        }
        renderJson(adminUserService.resetPassword(ids, pwd));
    }

    /**
     * @author zhangzhiwei
     * 退出登录
     */
    public void logout() {
        String token = BaseUtil.getToken(getRequest());
        if (!StrUtil.isEmpty(token)) {
            RedisManager.getRedis().del(token);
            removeCookie("Admin-Token");
        }
        renderJson(R.ok());
    }

    public void version() {
        renderJson(R.ok().put("name", BaseConstant.NAME).put("version", BaseConstant.VERSION));
    }


    public void ping() {
        List<String> arrays = new ArrayList<>();
        Connection connection = null;
        try {
            connection = Db.use().getConfig().getConnection();
            if (connection != null) {
                arrays.add("数据库连接成功");
            }
        } catch (Exception e) {
            arrays.add("数据库连接异常");
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    Log.getLog(getClass()).error("", e);
                }
            }

        }
        try {
            String ping = RedisManager.getRedis().ping();
            if ("PONG".equals(ping)) {
                arrays.add("Redis配置成功");
            } else {
                arrays.add("Redis配置失败");
            }
        } catch (Exception e) {
            arrays.add("Redis配置失败");
        }
        renderJson(R.ok().put("data", arrays));
    }

    /**
     * 注册
     *
     * @JSonParam("username") String username  用户名,
     * @JsonParam("password") String password  密码,
     * @JsonParam("email") String email  邮箱,
     * @JsonParam("mobile") String mobile  手机号,
     * @JsonParam("realname") String realname  机构名称,
     * @JsonParam("dept_id") Integer dept_id  所属机构编码,
     * @JsonParam("areaid") Integer areaid  所属省份编码,
     */
    @ApiDoc(url = "/register", method = "post")
    public void register() {
        try {
            String data = getRawData();

            AdminUser adminUser = JSON.parseObject(data, AdminUser.class);
            String username = CommonCryptogramUtil.doSm2Decrypt(adminUser.getUsername());
            String password = CommonCryptogramUtil.doSm2Decrypt(adminUser.getPassword());
            AdminUser user = AdminUser.dao.findFirst(Db.getSql("admin.user.queryByUserName"), adminUser.getUsername().trim());
            if (user != null) {
                renderJson(R.error("用户名已存在！"));
                return;
            }
            boolean isSave;
            String salt = IdUtil.simpleUUID();
            adminUser.setSalt(salt);

            adminUser.setUsername(username);

            password = BaseUtil.sign(username + password, adminUser.getSalt());
            adminUser.setPassword(password);
            adminUser.setCreateTime(new Date());
            adminUser.setAreaid(adminUser.getAreaid());
            isSave = adminUser.save();
            renderJson(R.ok().put("isSave", isSave ? R.ok() : R.error()));
        } catch (Exception e) {
            e.printStackTrace();
            renderJson(R.error());
        }

    }



    // -----------------------------------------


    @ApiDoc(url = "/getVerifyCode", method = "post")
    public void getVerifyCode(@Para("phone") String phone) {
        try {
            if(StringUtils.isEmpty(phone)){
                renderJson(R.error());
            }
            String code = ValidateCodeUtils.generateValidateCode(4).toString();
            setSessionAttr(phone, code);
            //hwSmsSenderService.getVerifyCode(phone, code);
            renderJson(R.ok().put("msg", "验证码短信发送成功!"));
        } catch (Exception e) {
            e.printStackTrace();
            renderJson(R.error());
        }
    }

    @ApiDoc(url = "/hnregister", method = "post")
    public void hnregister() {
        try {
            String sendPasswd = "";
            String data = getRawData();
            AdminUser adminUser = JSON.parseObject(data, AdminUser.class);
            String username = CommonCryptogramUtil.doSm2Decrypt(adminUser.getUsername());
            String password = CommonCryptogramUtil.doSm2Decrypt(adminUser.getPassword());
            sendPasswd = password;
            String phone = adminUser.getMobile();
            //String code = adminUser.getCode();
            //Object codeInSession = getSessionAttr(phone);
           // if (codeInSession != null && codeInSession.equals(code)) {
                AdminUser user = AdminUser.dao.findFirst(Db.getSql("admin.user.queryByUserName"), adminUser.getUsername().trim());
                if (user != null) {
                    renderJson(R.error("用户名已存在！"));
                    return;
                }
                boolean isSave;
                String salt = IdUtil.simpleUUID();
                adminUser.setSalt(salt);
                adminUser.setUsername(username);
                password = BaseUtil.sign(username + password, adminUser.getSalt());
                adminUser.setPassword(password);
                adminUser.setCreateTime(new Date());
                adminUser.setAreaid(adminUser.getAreaid());
                // hn 1827
//                hwSmsSenderService.sendPasswd2User(adminUser.getMobile(), adminUser.getMobile(), sendPasswd);
                isSave = adminUser.save();
                renderJson(R.ok().put("isSave", isSave ? R.ok() : R.error()));
            //}else{
               // renderJson(R.error("验证码错误！"));
           // }
        } catch (Exception e) {
            e.printStackTrace();
            renderJson(R.error());
        }
    }




}
